import pygame
import random
import sys

# 初始化 Pygame
try:
    pygame.init()
except Exception as e:
    print(f"Pygame 初始化失败: {e}")
    sys.exit(1)

# 定义颜色
WHITE = (255, 255, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)
BLACK = (0, 0, 0)
GRAY = (150, 150, 150)
HOVER_GRAY = (200, 200, 200)

# 游戏设置
WINDOW_WIDTH = 800
WINDOW_HEIGHT = 600
BLOCK_SIZE = 20
GAME_SPEED = 15

# 设置显示窗口
try:
    screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
    pygame.display.set_caption("贪吃蛇游戏")
except Exception as e:
    print(f"窗口创建失败: {e}")
    sys.exit(1)

# 字体设置
font = None
try:
    font = pygame.font.SysFont('Microsoft YaHei', 48)
except:
    try:
        font = pygame.font.SysFont('SimSun', 48)
    except:
        try:
            font = pygame.font.Font(None, 48)
            print("未找到微软雅黑或宋体字体，使用默认字体（可能不支持中文）")
        except Exception as e:
            print(f"字体加载失败: {e}")
            sys.exit(1)

# 方向向量
UP = (0, -1)
DOWN = (0, 1)
LEFT = (-1, 0)
RIGHT = (1, 0)

# 蛇类
class Snake:
    def __init__(self):
        self.length = 1
        self.positions = [(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2)]
        self.direction = random.choice([UP, DOWN, LEFT, RIGHT])
        self.color = GREEN
        self.score = 0

    def get_head_position(self):
        return self.positions[0]

    def update(self):
        try:
            cur = self.get_head_position()
            x, y = self.direction
            new = (cur[0] + (x * BLOCK_SIZE), cur[1] + (y * BLOCK_SIZE))
            self.positions.insert(0, new)
            if len(self.positions) > self.length:
                self.positions.pop()
            return True
        except Exception as e:
            print(f"蛇更新失败: {e}")
            return False

    def is_dead(self):
        """检查蛇是否死亡：撞到边框或自身"""
        try:
            head = self.get_head_position()
            # 检查是否撞到边框
            if head[0] < 0 or head[0] >= WINDOW_WIDTH or head[1] < 0 or head[1] >= WINDOW_HEIGHT:
                print("蛇撞到边框，死亡")
                return True
            # 检查是否撞到自身
            if head in self.positions[1:]:
                print("蛇撞到自身，死亡")
                return True
            return False
        except Exception as e:
            print(f"死亡判定失败: {e}")
            return True

    def reset(self):
        self.length = 1
        self.positions = [(WINDOW_WIDTH // 2, WINDOW_HEIGHT // 2)]
        self.direction = random.choice([UP, DOWN, LEFT, RIGHT])
        self.score = 0

    def render(self, surface):
        try:
            for p in self.positions:
                pygame.draw.rect(surface, self.color, (p[0], p[1], BLOCK_SIZE, BLOCK_SIZE))
        except Exception as e:
            print(f"蛇渲染失败: {e}")

# 食物类
class Food:
    def __init__(self):
        self.position = (0, 0)
        self.color = RED
        self.randomize_position()

    def randomize_position(self):
        try:
            self.position = (
                random.randint(0, (WINDOW_WIDTH - BLOCK_SIZE) // BLOCK_SIZE) * BLOCK_SIZE,
                random.randint(0, (WINDOW_HEIGHT - BLOCK_SIZE) // BLOCK_SIZE) * BLOCK_SIZE
            )
        except Exception as e:
            print(f"食物位置随机化失败: {e}")

    def render(self, surface):
        try:
            pygame.draw.rect(surface, self.color, (self.position[0], self.position[1], BLOCK_SIZE, BLOCK_SIZE))
        except Exception as e:
            print(f"食物渲染失败: {e}")

# 按钮类
class Button:
    def __init__(self, text, x, y, width, height):
        self.text = text
        self.rect = pygame.Rect(x, y, width, height)
        self.color = GRAY
        self.hover_color = HOVER_GRAY
        try:
            self.text_surface = font.render(text, True, WHITE)
        except Exception as e:
            print(f"按钮文本渲染失败: {e}")
            self.text_surface = font.render("错误", True, WHITE)

    def draw(self, surface):
        try:
            mouse_pos = pygame.mouse.get_pos()
            if self.rect.collidepoint(mouse_pos):
                pygame.draw.rect(surface, self.hover_color, self.rect)
            else:
                pygame.draw.rect(surface, self.color, self.rect)
            text_rect = self.text_surface.get_rect(center=self.rect.center)
            surface.blit(self.text_surface, text_rect)
        except Exception as e:
            print(f"按钮绘制失败: {e}")

    def is_clicked(self, event):
        try:
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                if self.rect.collidepoint(event.pos):
                    return True
        except Exception as e:
            print(f"按钮点击检测失败: {e}")
        return False

# 主菜单函数
def main_menu():
    start_button = Button("开始游戏", WINDOW_WIDTH // 2 - 100, WINDOW_HEIGHT // 2 - 25, 200, 50)
    quit_button = Button("退出游戏", WINDOW_WIDTH // 2 - 100, WINDOW_HEIGHT // 2 + 50, 200, 50)

    while True:
        try:
            screen.fill(BLACK)
            title = font.render("贪吃蛇游戏", True, WHITE)
            screen.blit(title, (WINDOW_WIDTH // 2 - title.get_width() // 2, WINDOW_HEIGHT // 4))
            start_button.draw(screen)
            quit_button.draw(screen)
            pygame.display.update()
        except Exception as e:
            print(f"主菜单绘制失败: {e}")
            pygame.quit()
            sys.exit(1)

        for event in pygame.event.get():
            try:
                if event.type == pygame.QUIT:
                    print("用户关闭窗口")
                    pygame.quit()
                    sys.exit()
                if start_button.is_clicked(event):
                    print("开始游戏按钮被点击")
                    return
                if quit_button.is_clicked(event):
                    print("退出游戏按钮被点击")
                    pygame.quit()
                    sys.exit()
            except Exception as e:
                print(f"主菜单事件处理失败: {e}")
                pygame.quit()
                sys.exit(1)

# 主游戏函数
def main():
    try:
        clock = pygame.time.Clock()
        snake = Snake()
        food = Food()
        print("进入主游戏循环")
        while True:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    print("游戏中关闭窗口")
                    pygame.quit()
                    sys.exit()
                elif event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_UP and snake.direction != DOWN:
                        snake.direction = UP
                    elif event.key == pygame.K_DOWN and snake.direction != UP:
                        snake.direction = DOWN
                    elif event.key == pygame.K_LEFT and snake.direction != RIGHT:
                        snake.direction = LEFT
                    elif event.key == pygame.K_RIGHT and snake.direction != LEFT:
                        snake.direction = RIGHT
                    elif event.key == pygame.K_q:
                        print("按 Q 返回主菜单")
                        return

            if not snake.update() or snake.is_dead():
                print("游戏结束：调用 game_over")
                game_over(snake.score)
                snake.reset()
                food.randomize_position()

            if snake.get_head_position() == food.position:
                snake.length += 1
                snake.score += 1
                food.randomize_position()

            screen.fill(BLACK)
            snake.render(screen)
            food.render(screen)
            score_text = font.render(f"得分: {snake.score}", True, WHITE)
            screen.blit(score_text, (10, 10))
            pygame.display.update()
            clock.tick(GAME_SPEED)
    except Exception as e:
        print(f"主游戏循环错误: {e}")
        pygame.quit()
        sys.exit(1)

# 游戏结束界面
def game_over(score):
    try:
        while True:
            screen.fill(BLACK)
            game_over_text = font.render("游戏结束！", True, WHITE)
            score_text = font.render(f"最终得分: {score}", True, WHITE)
            retry_text = font.render("按 R 重新开始", True, WHITE)
            menu_text = font.render("按 M 返回主菜单", True, WHITE)

            screen.blit(game_over_text, (WINDOW_WIDTH // 2 - game_over_text.get_width() // 2, WINDOW_HEIGHT // 4))
            screen.blit(score_text, (WINDOW_WIDTH // 2 - score_text.get_width() // 2, WINDOW_HEIGHT // 2 - 50))
            screen.blit(retry_text, (WINDOW_WIDTH // 2 - retry_text.get_width() // 2, WINDOW_HEIGHT // 2))
            screen.blit(menu_text, (WINDOW_WIDTH // 2 - menu_text.get_width() // 2, WINDOW_HEIGHT // 2 + 50))

            pygame.display.update()

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    print("游戏结束界面关闭窗口")
                    pygame.quit()
                    sys.exit()
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_r:
                        print("按 R 重新开始")
                        return
                    if event.key == pygame.K_m:
                        print("按 M 返回主菜单")
                        main_menu()
                        return
    except Exception as e:
        print(f"游戏结束界面错误: {e}")
        pygame.quit()
        sys.exit(1)

# 游戏主循环
try:
    print("程序启动")
    while True:
        main_menu()
        main()
except Exception as e:
    print(f"主循环错误: {e}")
    pygame.quit()
    sys.exit(1)